"""
统一包管理接口。

提供高级接口，自动为当前系统选择合适的包管理器。
支持在线和离线包管理器的分离管理。
"""

import os
import platform
from .core import detect_package_manager, detect_online_package_manager, detect_offline_package_manager
from .online import AptManager, YumManager, DnfManager, PacmanManager, ZypperManager, ApkManager
from .offline import DpkgManager, RpmManager


class OnlinePackageManager:
    """
    在线包管理器统一接口。
    
    专门管理在线包管理器（apt、yum、dnf、apk），支持软件安装、更新、升级等操作。
    """
    
    def __init__(self, sudo=False, preferred_manager=None):
        """
        初始化在线包管理器。
        
        参数:
            sudo (bool): 是否使用sudo执行特权操作，默认为False
            示例: sudo=True
            preferred_manager (str|None): 首选的在线包管理器名称（apt、yum、dnf、apk）
            示例: preferred_manager="apt"
        """
        self.sudo = sudo
        self.preferred_manager = preferred_manager
        self._manager = None
        self._detect_and_set_manager()
    
    def _detect_and_set_manager(self):
        """检测并设置合适的在线包管理器。"""
        # 如果指定了首选管理器，尝试使用它
        if self.preferred_manager:
            manager_map = {
                'apt': AptManager,
                'yum': YumManager,
                'dnf': DnfManager,
                'pacman': PacmanManager,
                'zypper': ZypperManager,
                'apk': ApkManager
            }
            
            if self.preferred_manager in manager_map:
                manager_class = manager_map[self.preferred_manager]
                self._manager = manager_class(sudo=self.sudo)
                if self._manager.is_available():
                    return
                else:
                    self._manager = None
        
        # 如果首选管理器不可用或未指定，则自动检测在线包管理器
        detected = detect_online_package_manager()
        if detected:
            detected.sudo = self.sudo
            self._manager = detected
        else:
            # 备用方案：尝试所有在线管理器
            managers_to_try = [
                AptManager(sudo=self.sudo),
                DnfManager(sudo=self.sudo),
                YumManager(sudo=self.sudo),
                PacmanManager(sudo=self.sudo),
                ZypperManager(sudo=self.sudo),
                ApkManager(sudo=self.sudo)
            ]
            
            for manager in managers_to_try:
                if manager.is_available():
                    self._manager = manager
                    break
    
    def get_current_manager(self):
        """
        获取当前活动的在线包管理器。
        
        返回:
            OnlinePackageManager|None: 当前在线包管理器实例，如果不可用返回None
        """
        return self._manager
    
    def get_manager_name(self):
        """
        获取当前活动在线包管理器的名称。
        
        返回:
            str|None: 在线包管理器名称，如果不可用返回None
        """
        return self._manager.name if self._manager else None
    
    def is_manager_available(self):
        """
        检查是否有可用的在线包管理器。
        
        返回:
            bool: 如果在线包管理器可用返回True，否则返回False
        """
        return self._manager is not None
    
    def install(self, packages):
        """
        使用检测到的在线管理器安装软件包。
        
        参数:
            packages (str|list): 要安装的软件包名称或列表
            示例: packages="curl" 或 packages=["curl", "wget"]
        
        返回:
            bool: 安装成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的在线包管理器")
        return self._manager.install(packages)
    
    def remove(self, packages):
        """
        使用检测到的在线管理器移除软件包。
        
        参数:
            packages (str|list): 要移除的软件包名称或列表
            示例: packages="curl" 或 packages=["curl", "wget"]
        
        返回:
            bool: 移除成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的在线包管理器")
        return self._manager.remove(packages)
    
    def update(self):
        """
        使用检测到的在线管理器更新软件包列表。
        
        返回:
            bool: 更新成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的在线包管理器")
        return self._manager.update()
    
    def upgrade(self, packages=None):
        """
        使用检测到的在线管理器升级软件包。
        
        参数:
            packages (str|list|None): 要升级的软件包名称或列表，None表示升级所有包
            示例: packages="curl" 或 packages=["curl", "wget"] 或 packages=None
        
        返回:
            bool: 升级成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的在线包管理器")
        return self._manager.upgrade(packages)
    
    def search(self, pattern):
        """
        使用检测到的在线管理器搜索软件包。
        
        参数:
            pattern (str): 搜索模式
            示例: pattern="python"
        
        返回:
            list: 包含匹配软件包信息的字典列表
        """
        if not self._manager:
            raise RuntimeError("没有可用的在线包管理器")
        return self._manager.search(pattern)
    
    def info(self, package):
        """
        使用检测到的在线管理器获取软件包信息。
        
        参数:
            package (str): 软件包名称
            示例: package="python3"
        
        返回:
            dict|None: 软件包信息字典，如果包不存在返回None
        """
        if not self._manager:
            raise RuntimeError("没有可用的在线包管理器")
        return self._manager.info(package)
    
    def list_installed(self):
        """
        使用检测到的在线管理器列出已安装的软件包。
        
        返回:
            list: 包含已安装软件包信息的字典列表
        """
        if not self._manager:
            raise RuntimeError("没有可用的在线包管理器")
        return self._manager.list_installed()
    
    def clean_cache(self):
        """
        清理软件包缓存。
        
        返回:
            bool: 清理成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的在线包管理器")
        return self._manager.clean_cache()
    
    def autoremove(self):
        """
        移除自动安装但不再需要的软件包。
        
        返回:
            bool: 移除成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的在线包管理器")
        if hasattr(self._manager, 'autoremove'):
            return self._manager.autoremove()
        else:
            return True  # 某些管理器可能没有autoremove功能


class OfflinePackageManager:
    """
    离线包管理器统一接口。
    
    专门管理离线包管理器（dpkg、rpm），支持软件包安装、移除、验证等操作。
    注意：离线包管理器不支持软件更新、升级等需要网络连接的操作。
    """
    
    def __init__(self, sudo=False, preferred_manager=None):
        """
        初始化离线包管理器。
        
        参数:
            sudo (bool): 是否使用sudo执行特权操作，默认为False
            示例: sudo=True
            preferred_manager (str|None): 首选的离线包管理器名称（dpkg、rpm）
            示例: preferred_manager="dpkg"
        """
        self.sudo = sudo
        self.preferred_manager = preferred_manager
        self._manager = None
        self._detect_and_set_manager()
    
    def _detect_and_set_manager(self):
        """检测并设置合适的离线包管理器。"""
        # 如果指定了首选管理器，尝试使用它
        if self.preferred_manager:
            manager_map = {
                'dpkg': DpkgManager,
                'rpm': RpmManager
            }
            
            if self.preferred_manager in manager_map:
                manager_class = manager_map[self.preferred_manager]
                self._manager = manager_class(sudo=self.sudo)
                if self._manager.is_available():
                    return
                else:
                    self._manager = None
        
        # 如果首选管理器不可用或未指定，则自动检测离线包管理器
        detected = detect_offline_package_manager()
        if detected:
            detected.sudo = self.sudo
            self._manager = detected
        else:
            # 备用方案：尝试所有离线管理器
            managers_to_try = [
                DpkgManager(sudo=self.sudo),
                RpmManager(sudo=self.sudo)
            ]
            
            for manager in managers_to_try:
                if manager.is_available():
                    self._manager = manager
                    break
    
    def get_current_manager(self):
        """
        获取当前活动的离线包管理器。
        
        返回:
            OfflinePackageManager|None: 当前离线包管理器实例，如果不可用返回None
        """
        return self._manager
    
    def get_manager_name(self):
        """
        获取当前活动离线包管理器的名称。
        
        返回:
            str|None: 离线包管理器名称，如果不可用返回None
        """
        return self._manager.name if self._manager else None
    
    def is_manager_available(self):
        """
        检查是否有可用的离线包管理器。
        
        返回:
            bool: 如果离线包管理器可用返回True，否则返回False
        """
        return self._manager is not None
    
    def install(self, packages):
        """
        使用检测到的离线管理器安装软件包。
        
        参数:
            packages (str|list): 要安装的软件包名称或列表
            示例: packages="curl" 或 packages=["curl", "wget"]
        
        返回:
            bool: 安装成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的离线包管理器")
        return self._manager.install(packages)
    
    def remove(self, packages):
        """
        使用检测到的离线管理器移除软件包。
        
        参数:
            packages (str|list): 要移除的软件包名称或列表
            示例: packages="curl" 或 packages=["curl", "wget"]
        
        返回:
            bool: 移除成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的离线包管理器")
        return self._manager.remove(packages)
    
    def update(self):
        """
        离线包管理器不支持更新操作。
        
        返回:
            bool: 总是返回False，因为离线包管理器不支持更新
        """
        raise RuntimeError("离线包管理器不支持更新操作")
    
    def upgrade(self, packages=None):
        """
        离线包管理器不支持升级操作。
        
        参数:
            packages (str|list|None): 此参数对离线包管理器无效
        
        返回:
            bool: 总是返回False，因为离线包管理器不支持升级
        """
        raise RuntimeError("离线包管理器不支持升级操作")
    
    def search(self, pattern):
        """
        使用检测到的离线管理器搜索软件包。
        
        参数:
            pattern (str): 搜索模式
            示例: pattern="python"
        
        返回:
            list: 包含匹配软件包信息的字典列表
        """
        if not self._manager:
            raise RuntimeError("没有可用的离线包管理器")
        return self._manager.search(pattern)
    
    def info(self, package):
        """
        使用检测到的离线管理器获取软件包信息。
        
        参数:
            package (str): 软件包名称
            示例: package="python3"
        
        返回:
            dict|None: 软件包信息字典，如果包不存在返回None
        """
        if not self._manager:
            raise RuntimeError("没有可用的离线包管理器")
        return self._manager.info(package)
    
    def list_installed(self):
        """
        使用检测到的离线管理器列出已安装的软件包。
        
        返回:
            list: 包含已安装软件包信息的字典列表
        """
        if not self._manager:
            raise RuntimeError("没有可用的离线包管理器")
        return self._manager.list_installed()
    
    def verify(self, package):
        """
        验证软件包完整性。
        
        参数:
            package (str): 要验证的软件包名称
            示例: package="python3"
        
        返回:
            bool: 验证成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的离线包管理器")
        return self._manager.verify(package)
    
    def install_from_file(self, file_path):
        """
        从本地文件安装软件包。
        
        参数:
            file_path (str): 软件包文件路径
            示例: file_path="/tmp/package.rpm"
        
        返回:
            bool: 安装成功返回True，失败返回False
        """
        if not self._manager:
            raise RuntimeError("没有可用的离线包管理器")
        return self._manager.install_from_file(file_path)


def get_package_manager(sudo=False, manager_name=None):
    """
    获取包管理器实例。
    
    参数:
        sudo (bool): 是否使用sudo，默认为False
        示例: sudo=True
        manager_name (str|None): 特定的包管理器名称（apt、yum、dnf、dpkg、rpm）
        示例: manager_name="apt"
    
    返回:
        PackageManager|None: 包管理器实例，如果不可用返回None
    """
    if manager_name:
        manager_map = {
            'apt': AptManager,
            'yum': YumManager,
            'dnf': DnfManager,
            'pacman': PacmanManager,
            'zypper': ZypperManager,
            'apk': ApkManager,
            'dpkg': DpkgManager,
            'rpm': RpmManager
        }
        
        if manager_name in manager_map:
            manager = manager_map[manager_name](sudo=sudo)
            if manager.is_available():
                return manager
    
    # 自动检测
    return detect_package_manager()


def list_available_managers():
    """
    列出系统上所有可用的包管理器。
    
    返回:
        list: 可用的包管理器名称列表
    """
    available = []
    
    managers = [
        ('apt', AptManager),
        ('yum', YumManager),
        ('dnf', DnfManager),
        ('pacman', PacmanManager),
        ('zypper', ZypperManager),
        ('apk', ApkManager),
        ('dpkg', DpkgManager),
        ('rpm', RpmManager)
    ]
    
    for name, manager_class in managers:
        try:
            manager = manager_class()
            if manager.is_available():
                available.append(name)
        except:
            pass
    
    return available